package org.yoki.edu.lib;

import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import com.sun.jna.Memory;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.ptr.IntByReference;

public class NetSDKTools {
	static NetSDKLib NetSdk        = NetSDKLib.COMMON_INSTANCE;
    static NetSDKLib ConfigSdk     = NetSDKLib.CONFIG_INSTANCE;

	public static void GetPointerData(Pointer pNativeData, Structure pJavaStu)
	{
		GetPointerDataToStruct(pNativeData, 0, pJavaStu);
	}

	public static void GetPointerDataToStruct(Pointer pNativeData, long OffsetOfpNativeData, Structure pJavaStu) {
		pJavaStu.write();
		Pointer pJavaMem = pJavaStu.getPointer();
		pJavaMem.write(0, pNativeData.getByteArray(OffsetOfpNativeData, pJavaStu.size()), 0,
				pJavaStu.size());
		pJavaStu.read();
	}
	
	public static void GetPointerDataToStructArr(Pointer pNativeData, Structure []pJavaStuArr) {
		long offset = 0;
		for (int i=0; i<pJavaStuArr.length; ++i)
		{
			GetPointerDataToStruct(pNativeData, offset, pJavaStuArr[i]);
			offset += pJavaStuArr[i].size();
		}
	}
	
	/**
	 * 将结构体数组拷贝到内存
	 * @param pNativeData 
	 * @param pJavaStuArr
	 */
	public static void SetStructArrToPointerData(Structure []pJavaStuArr, Pointer pNativeData) {
		long offset = 0;
		for (int i = 0; i < pJavaStuArr.length; ++i) {
			SetStructDataToPointer(pJavaStuArr[i], pNativeData, offset);
			offset += pJavaStuArr[i].size();
		}
	}
	
	public static void SetStructDataToPointer(Structure pJavaStu, Pointer pNativeData, long OffsetOfpNativeData){
		pJavaStu.write();
		Pointer pJavaMem = pJavaStu.getPointer();
		pNativeData.write(OffsetOfpNativeData, pJavaMem.getByteArray(0, pJavaStu.size()), 0, pJavaStu.size());
	}
	
	public static void ByteArrToStructure(byte[] pNativeData, Structure pJavaStu) {
		pJavaStu.write();
		Pointer pJavaMem = pJavaStu.getPointer();
		pJavaMem.write(0, pNativeData, 0, pJavaStu.size());
		pJavaStu.read();
	}

	public static void ByteArrZero(byte[] dst) {
		// 清零
		for (int i = 0; i < dst.length; ++i) {
			dst[i] = 0;
		}
	}

	public static void StringToByteArr(String src, byte[] dst) {
		try {
			byte[] GBKBytes = src.getBytes("GBK");
			for (int i = 0; i < GBKBytes.length; i++) {
				dst[i] = (byte) GBKBytes[i];
			}
		} catch (Exception e1) {
			e1.printStackTrace();
		}
	}
	
	public static long GetFileSize(String filePath)
	{
		File f = new File(filePath);
		if (f.exists() && f.isFile()) {
			return f.length();
		}
		else
		{
			return 0;
		}
	}
	
	public static boolean ReadAllFileToMemory(String file, Memory mem)
	{
		if (mem != Memory.NULL)
		{
			long fileLen = GetFileSize(file);
			if (fileLen <= 0)
			{
				return false;
			}
			
			try {
				File infile = new File(file);
				if (infile.canRead())
				{
					FileInputStream in = new FileInputStream(infile);
					int buffLen = 1024; 
					byte[] buffer = new byte[buffLen];
					long currFileLen = 0;
					int readLen = 0;
					while (currFileLen < fileLen)
					{
						readLen = in.read(buffer);
						mem.write(currFileLen, buffer, 0, readLen);
						currFileLen += readLen;
					}
					
					in.close();
					return true;
				}
		        else
		        {
		        	System.err.println("Failed to open file %s for read!!!\n");
		            return false;
		        }
			}catch (Exception e)
			{
				System.err.println("Failed to open file %s for read!!!\n");
				System.out.println(e);
				e.printStackTrace();
			}
		}
		
		return false;
	}
	
	public static void savePicture(Pointer pBuf, int dwBufSize, String sDstFile)
	{
        try
        {
        	DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(sDstFile)));
        	out.write(pBuf.getByteArray(0, dwBufSize), 0, dwBufSize);
        	out.close();
        } catch (Exception e){
        	e.printStackTrace();
        }
	}
	
	public static void savePicture(Pointer pBuf, int dwBufOffset, int dwBufSize, String sDstFile)
	{
        try
        {
        	DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(sDstFile)));
        	out.write(pBuf.getByteArray(dwBufOffset, dwBufSize), 0, dwBufSize);
        	out.close();
        } catch (Exception e){
        	e.printStackTrace();
        }
	}

	/**
	 * 获取多个配置
	 * @param hLoginHandle 登陆句柄
	 * @param nChn 通道号，-1 表示全通道
	 * @param strCmd 配置名称
	 * @param cmdObjects 配置对应的结构体对象
	 * @return 成功返回实际获取到的配置个数
	 */
	public static int GetDevConfig(NativeLong hLoginHandle, int nChn, String strCmd, Structure[] cmdObjects)
	{
		int error[] = {0};
		int nBufferLen = 2*1024*1024;
	    byte[] strBuffer = new byte[nBufferLen];
	    
	    if(!NetSdk.CLIENT_GetNewDevConfig(hLoginHandle, strCmd , nChn, strBuffer, nBufferLen, error, 3000))
	    {
	    	System.err.printf("Get %s Config Failed!Last Error = %x\n" , strCmd , NetSdk.CLIENT_GetLastError());
	    	return -1;
	    }
	    
	    IntByReference retLength = new IntByReference(0);
	    int memorySize = cmdObjects.length * cmdObjects[0].size();
	    Pointer objectsPointer = new Memory(memorySize);
	    objectsPointer.clear(memorySize);
	    
	    NetSDKTools.SetStructArrToPointerData(cmdObjects, objectsPointer);
	    
		if (!ConfigSdk.CLIENT_ParseData(strCmd, strBuffer, objectsPointer, memorySize, retLength.getPointer())) {		     		
     		System.err.println("Parse " + strCmd + " Config Failed!");
     		return -1;
		}
		
		NetSDKTools.GetPointerDataToStructArr(objectsPointer, cmdObjects);
		
		return (retLength.getValue() / cmdObjects[0].size());
	}

	/**
	 * 获取单个配置
	 * @param hLoginHandle 登陆句柄
	 * @param nChn 通道号，-1 表示全通道
	 * @param strCmd 配置名称
	 * @param cmdObject 配置对应的结构体对象
	 * @return 成功返回 true 
	 */
	public static boolean GetDevConfig(NativeLong hLoginHandle, int nChn, String strCmd, Structure cmdObject) {
		boolean result = false;
		int error[] = {0};
		int nBufferLen = 2*1024*1024;
	    byte[] strBuffer = new byte[nBufferLen];
	   
	    if(NetSdk.CLIENT_GetNewDevConfig( hLoginHandle, strCmd , nChn, strBuffer, nBufferLen,error,3000) )
	    {  
	    	cmdObject.write();
			if (ConfigSdk.CLIENT_ParseData(strCmd, strBuffer, cmdObject.getPointer(),
					cmdObject.size(), null))
	     	{
				cmdObject.read();
	     		result = true;
	     	}
	     	else
	     	{
	     		System.err.println("Parse " + strCmd + " Config Failed!");
	     		result = false;
		 	}
	    }
		else
		{
			 System.err.printf("Get %s Config Failed!Last Error = %x\n" , strCmd , NetSdk.CLIENT_GetLastError());
			 result = false;
		}
			
	    return result;
	}
	
	/**
	 * 设置多个配置
	 * @param hLoginHandle 登陆句柄
	 * @param nChn 通道号，-1 表示全通道
	 * @param strCmd 配置名称
	 * @param cmdObjects 配置对应的结构体对象
	 * @return 成功返回 true
	 */
	public static boolean SetDevConfigArr(NativeLong hLoginHandle, int nChn, String strCmd, Structure[] cmdObjects) {
        boolean result = false;
    	int nBufferLen = 2*1024*1024;
        byte szBuffer[] = new byte[nBufferLen];
        for(int i=0; i<nBufferLen; i++)szBuffer[i]=0;
        int error[] = {0};
        int restart[] = {0};    

	    int memorySize = cmdObjects.length * cmdObjects[0].size();
	    Pointer objectsPointer = new Memory(memorySize);
	    objectsPointer.clear(memorySize);
        
	    NetSDKTools.SetStructArrToPointerData(cmdObjects, objectsPointer);
        
		if (ConfigSdk.CLIENT_PacketData(strCmd, objectsPointer, memorySize, szBuffer, nBufferLen))
        {
        	if( NetSdk.CLIENT_SetNewDevConfig(hLoginHandle, strCmd , nChn , szBuffer, nBufferLen, error, restart, 3000))
        	{
        		result = true;
        	}
        	else
        	{
        		 System.err.printf("Set %s Config Failed! Last Error = %x\n" , strCmd , NetSdk.CLIENT_GetLastError());
	        	 result = false;
        	}
        }
        else
        {
        	System.err.println("Packet " + strCmd + " Config Failed!");
         	result = false;
        }
        
        return result;
    }
	
	/**
	 * 设置单个配置
	 * @param hLoginHandle 登陆句柄
	 * @param nChn 通道号，-1 表示全通道
	 * @param strCmd 配置名称
	 * @param cmdObjects 配置对应的结构体对象
	 * @return 成功返回 true
	 */
	public static boolean SetDevConfig(NativeLong hLoginHandle, int nChn, String strCmd, Structure cmdObject) {
        boolean result = false;
    	int nBufferLen = 2*1024*1024;
        byte szBuffer[] = new byte[nBufferLen];
        for(int i=0; i<nBufferLen; i++)szBuffer[i]=0;
        int error[] = {0};
        int restart[] = {0};
        
		cmdObject.write();
		if (ConfigSdk.CLIENT_PacketData(strCmd, cmdObject.getPointer(), cmdObject.size(),
				szBuffer, nBufferLen))
        {	
			cmdObject.read();
        	if( NetSdk.CLIENT_SetNewDevConfig(hLoginHandle, strCmd , nChn , szBuffer, nBufferLen, error, restart, 3000))
        	{
        		result = true;
        	}
        	else
        	{
        		 System.err.printf("Set %s Config Failed! Last Error = %x\n" , strCmd , NetSdk.CLIENT_GetLastError());
	        	 result = false;
        	}
        }
        else
        {
        	System.err.println("Packet " + strCmd + " Config Failed!");
         	result = false;
        }
        
        return result;
    }
}
